#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
分页工具模块

提供通用的分页功能，可用于各种数据源的分页查询
"""

from typing import Dict, List, Any, TypeVar, Generic, Optional, Union, Callable
from sqlalchemy.orm.query import Query

# 定义泛型类型变量，用于表示任意类型的项目
T = TypeVar('T')


class Paginator(Generic[T]):
    """
    通用分页器类
    
    用于处理各种数据源的分页查询，支持SQLAlchemy查询和普通列表
    """
    
    def __init__(self, items: List[T], total: int, page: int = 1, per_page: int = 20):
        """
        初始化分页器
        
        Args:
            items: 当前页的项目列表
            total: 总记录数
            page: 当前页码，从1开始
            per_page: 每页记录数
        """
        self.items = items
        self.total = total
        self.page = max(1, page)  # 确保页码至少为1
        self.per_page = max(1, per_page)  # 确保每页记录数至少为1
        
        # 计算总页数
        self.pages = (total + per_page - 1) // per_page if total > 0 else 0
        
        # 计算是否有上一页和下一页
        self.has_prev = page > 1
        self.has_next = page < self.pages
        
        # 计算上一页和下一页的页码
        self.prev_page = page - 1 if self.has_prev else None
        self.next_page = page + 1 if self.has_next else None
    
    def to_dict(self) -> Dict[str, Any]:
        """
        将分页结果转换为字典
        
        Returns:
            Dict: 包含分页信息和项目列表的字典
        """
        return {
            'items': self.items,
            'total': self.total,
            'page': self.page,
            'per_page': self.per_page,
            'pages': self.pages,
            'has_prev': self.has_prev,
            'has_next': self.has_next,
            'prev_page': self.prev_page,
            'next_page': self.next_page
        }


def paginate_query(query: Query, page: int = 1, per_page: int = 20, 
                  order_by: Optional[Union[str, Callable]] = None) -> Paginator:
    """
    对SQLAlchemy查询进行分页
    
    Args:
        query: SQLAlchemy查询对象
        page: 页码，从1开始
        per_page: 每页记录数
        order_by: 排序字段或排序函数，可以是字符串或可调用对象
                 如果是字符串，格式为'字段名 asc'或'字段名 desc'
                 如果是可调用对象，将被传递给query.order_by()
    
    Returns:
        Paginator: 分页结果对象
    
    Examples:
        # 基本用法
        result = paginate_query(User.query.filter(User.active == True), page=2, per_page=10)
        
        # 使用字符串指定排序
        result = paginate_query(User.query, page=1, per_page=20, order_by='created_at desc')
        
        # 使用函数指定排序
        result = paginate_query(User.query, page=1, per_page=20, 
                              order_by=lambda q: q.order_by(User.created_at.desc()))
    """
    # 获取总记录数
    total = query.count()
    
    # 应用排序
    if order_by is not None:
        if isinstance(order_by, str):
            # 解析排序字符串
            parts = order_by.split()
            if len(parts) >= 2 and parts[-1].lower() in ('asc', 'desc'):
                field = ' '.join(parts[:-1])
                direction = parts[-1].lower()
                
                # 动态获取模型类和字段
                model = query.column_descriptions[0]['entity']
                attr = getattr(model, field)
                
                # 应用排序方向
                if direction == 'desc':
                    query = query.order_by(attr.desc())
                else:
                    query = query.order_by(attr.asc())
            else:
                # 如果没有指定方向，默认为升序
                field = order_by
                model = query.column_descriptions[0]['entity']
                attr = getattr(model, field)
                query = query.order_by(attr.asc())
        else:
            # 使用可调用对象进行排序
            query = order_by(query)
    
    # 获取当前页数据
    items = query.offset((page - 1) * per_page).limit(per_page).all()
    
    # 创建并返回分页器对象
    return Paginator(items=items, total=total, page=page, per_page=per_page)


def paginate_list(items: List[T], page: int = 1, per_page: int = 20) -> Paginator[T]:
    """
    对普通列表进行分页
    
    Args:
        items: 要分页的列表
        page: 页码，从1开始
        per_page: 每页记录数
    
    Returns:
        Paginator: 分页结果对象
    """
    # 获取总记录数
    total = len(items)
    
    # 计算起始和结束索引
    start = (page - 1) * per_page
    end = min(start + per_page, total)
    
    # 获取当前页数据
    page_items = items[start:end]
    
    # 创建并返回分页器对象
    return Paginator(items=page_items, total=total, page=page, per_page=per_page)